package com.dingreading.cloud.admin.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.dingreading.cloud.admin.dto.CourseTrainTypesDto;
import com.dingreading.cloud.admin.entity.CourseTrainTypes;
import com.dingreading.cloud.admin.entity.table.CourseTrainTypesTableDef;
import com.dingreading.cloud.admin.mapper.CourseTrainTypesMapper;
import com.dingreading.cloud.admin.service.CourseTrainService;
import com.dingreading.cloud.admin.service.CourseTrainTypesService;
import com.dingreading.cloud.admin.util.CdnUrlUtil;
import com.dingreading.cloud.admin.util.CourseTrainUtil;
import com.dingreading.cloud.admin.util.TreeJsonUtil;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.NepUtil;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 叮叮线下培训分类表 服务层实现。
 *
 * @author EDY
 * @since 2025-11-17
 */
@Service
public class CourseTrainTypesServiceImpl extends BaseServiceImpl<CourseTrainTypesMapper, CourseTrainTypes, CourseTrainTypesTableDef> implements CourseTrainTypesService {

    @Override
    protected CourseTrainTypesTableDef getTable() {
        return CourseTrainTypesTableDef.courseTrainTypes;
    }

    @Resource
    private CdnUrlUtil cdnUrlUtil;
    @Resource
    private CourseTrainService courseTrainService;

    @Override
    public R<Object> getMainTypes(String headStaffUid, String headStaffName) {
        QueryCondition condition = QueryCondition.createEmpty()
                .and(table.parentId.eq(0L));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.showOrder.asc());

        List<CourseTrainTypes> courseTrainTypes = getMapper().selectListByQuery(wrapper);
        return R.ok(courseTrainTypes);
    }

    @Override
    public R<Object> treeList(HttpServletRequest request, String headStaffUid, String headStaffName, String uid) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工参数缺少");
        JSONArray treeJson = new JSONArray();
        CourseTrainTypes courseTrainTypes = null;
        if (StringUtils.isNotBlank(uid)) {
            courseTrainTypes = getMapper().selectOneByCondition(table.uid.eq(uid));
        }

        QueryCondition condition = QueryCondition.createEmpty();
        if (courseTrainTypes != null && courseTrainTypes.getId() != null)
            condition.and(table.mainId.eq(courseTrainTypes.getId()));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.showOrder.asc());

        List<CourseTrainTypesDto> courseTrainTypesList = getMapper().selectListByQueryAs(wrapper, CourseTrainTypesDto.class);
        // 如果courseTrainTypesList的examUrl不为空就添加cdn处理
        for (CourseTrainTypesDto dto : courseTrainTypesList) {
            if (StringUtils.isNotBlank(dto.getExamUrl())) {
                R<String> r = cdnUrlUtil.getCdnUrl(request, dto.getExamUrl());
                if (R.isError(r))
                    return R.fail(r.getMsg());
                dto.setCdnExamUrl(r.getData());
            }
        }
        if (CollectionUtils.isNotEmpty(courseTrainTypesList)) {
            treeJson = TreeJsonUtil.createCourseTrainTypesTreeJson(courseTrainTypesList);
        }
        return R.ok(treeJson);
    }

    @Override
    public R<Object> newMainType(String headStaffUid, String headStaffName, String uid, String typeName, Integer showOrder, Integer levelEnd) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工参数缺少");
        if (StringUtils.isBlank(typeName))
            return R.fail("分类名称参数缺少");
        if (levelEnd == null)
            return R.fail("是否最后一级参数缺少");

        if (StringUtils.isBlank(uid)) {
            // 新增
            QueryCondition condition = QueryCondition.createEmpty()
                    .and(table.typeName.eq(typeName))
                    .and(table.parentId.eq(0L));
            long l = getMapper().selectCountByCondition(condition);

            if (l > 0) return R.fail("分类名重复了");
            // 获取最大的主分类展示序号
            QueryWrapper wrapper = QueryWrapper.create()
                    .select(QueryMethods.max(table.showOrder))
                    .where(table.parentId.eq(0L));

            Integer currentMaxOrder = getMapper().selectObjectByQueryAs(wrapper, Integer.class);
            Integer maxShowOrder = NepUtil.nullToZero(currentMaxOrder) + 1;

            CourseTrainTypes data = CourseTrainUtil.newMainCourseTrainTypes(
                    typeName, levelEnd, maxShowOrder, headStaffUid, headStaffName
            );

            boolean b = saveOrUpdate(data);
            if (!b) return R.fail("保存信息失败");

            boolean update = UpdateChain.of(CourseTrainTypes.class)
                    .set(table.mainId, data.getId())
                    .set(table.nodes, String.valueOf(data.getId()).concat(","))
                    .where(table.id.eq(data.getId()))
                    .update();
            if (!update) return R.fail("保存节点信息失败");
        } else {
            // 修改
            CourseTrainTypes trainTypes = getMapper().selectOneByCondition(table.uid.eq(uid));
            if (trainTypes == null) return R.fail("分类获取失败");

            QueryCondition condition = QueryCondition.createEmpty()
                    .and(table.typeName.eq(typeName))
                    .and(table.parentId.eq(0L))
                    .and(table.uid.ne(uid));
            long l = getMapper().selectCountByCondition(condition);
            if (l > 0) return R.fail("分类名重复了");

            if (typeName != null)
                trainTypes.setTypeName(typeName);
            if (showOrder != null)
                trainTypes.setShowOrder(showOrder);
            trainTypes.setLastStaffUid(headStaffUid);
            trainTypes.setLastStaffName(headStaffName);
            boolean b = saveOrUpdate(trainTypes);
            if (!b) return R.fail("修改信息失败");
        }
        return R.ok();
    }

    @Override
    public R<Object> newChildType(String headStaffUid, String headStaffName, String parentUid, String uid, String typeName, Integer levelEnd) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工参数缺少");
        if (StringUtils.isBlank(parentUid))
            return R.fail("上级分类参数缺少");
        if (StringUtils.isBlank(typeName))
            return R.fail("分类名称参数缺少");
        if (levelEnd == null)
            return R.fail("是否最后一级参数缺少");

        CourseTrainTypes parentCourseTypes = getMapper().selectOneByCondition(table.uid.eq(parentUid));

        if (parentCourseTypes == null) return R.fail("上级分类获取失败");
        if (parentCourseTypes.getLevelEnd().equals(1)) return R.fail("上级分类是最后一级，不能新增子分类");
        Long parentId = parentCourseTypes.getId();

        CourseTrainTypes mainCourseTypes = getById(parentCourseTypes.getMainId());
        if (mainCourseTypes == null) return R.fail("主分类获取失败");

        if (StringUtils.isBlank(uid)) {
            // 新增
            // 获取分类内的最大序号
            QueryWrapper wrapper = QueryWrapper.create()
                    .select(QueryMethods.max(table.showOrder))
                    .where(table.parentId.eq(parentId));

            Integer currentMaxOrder = getMapper().selectObjectByQueryAs(wrapper, Integer.class);
            Integer maxShowOrder = NepUtil.nullToZero(currentMaxOrder) + 1;

            // 获取层级序号
            Integer levelIndex = NepUtil.nullToZero(parentCourseTypes.getLevelIndex()) + 1;
            if (levelEnd != 1) {
                levelEnd = 0;
            }
            CourseTrainTypes childCourseTypes = CourseTrainUtil.newChildCourseTrainTypes(
                    mainCourseTypes.getId(), parentId,
                    typeName, maxShowOrder, levelEnd, levelIndex, headStaffUid, headStaffName
            );
            boolean b = saveOrUpdate(childCourseTypes);
            if (!b) return R.fail("保存信息失败");
            boolean update = UpdateChain.of(CourseTrainTypes.class)
                    .set(table.nodes, parentCourseTypes.getNodes().concat(String.valueOf(childCourseTypes.getId())).concat(","))
                    .where(table.id.eq(childCourseTypes.getId()))
                    .update();
            if (!update) return R.fail("保存节点信息失败");
        } else {
            // 修改
            CourseTrainTypes trainTypes = getMapper().selectOneByCondition(table.uid.eq(uid));
            if (trainTypes == null) return R.fail("分类获取失败");

            if (typeName != null)
                trainTypes.setTypeName(typeName);

            trainTypes.setLastStaffUid(headStaffUid);
            trainTypes.setLastStaffName(headStaffName);
            boolean b = saveOrUpdate(trainTypes);
            if (!b) return R.fail("修改信息失败");
        }
        return R.ok();
    }

    @Override
    public R<Object> getByUid(HttpServletRequest request, String headStaffUid, String headStaffName, String uid) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工参数缺少");
        if (StringUtils.isBlank(uid))
            return R.fail("分类参数缺少");
        QueryWrapper wrapper = QueryWrapper.create()
                .where(table.uid.eq(uid));
        CourseTrainTypesDto courseTrainTypesDto = getMapper().selectOneByQueryAs(wrapper, CourseTrainTypesDto.class);
        String examUrl = courseTrainTypesDto.getExamUrl();
        if (courseTrainTypesDto == null && StringUtils.isNotBlank(examUrl)){
            R<String> r = cdnUrlUtil.getCdnUrl(request, examUrl);
            if (R.isError(r))
                return R.fail(r.getMsg());
            courseTrainTypesDto.setCdnExamUrl(r.getData());
        }
        return R.ok(courseTrainTypesDto);
    }

    @Override
    public R<Object> updateEnabled(String headStaffUid, String headStaffName, String uid, Integer enabled) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工参数缺少");
        if (StringUtils.isBlank(uid))
            return R.fail("分类参数缺少");
        if (enabled == null)
            return R.fail("状态参数缺少");

        CourseTrainTypes data = getMapper().selectOneByCondition(table.uid.eq(uid));
        if (data == null) return R.fail("获取失败");
        Long id = data.getId();

        if (data.getParentId().equals(0L)) {
            // 如果是主分类，适用其下所有分类
            boolean update = UpdateChain.of(CourseTrainTypes.class)
                    .set(table.enabled, enabled)
                    .where(table.mainId.eq(id))
                    .update();
            if (!update) return R.fail("修改状态信息失败");
        } else {
            // 如果是子分类，适用其下所有分类
            QueryCondition condition = QueryCondition.createEmpty();
            condition.and(table.id.eq(id).or(table.parentId.eq(id)));
            boolean update = UpdateChain.of(CourseTrainTypes.class)
                    .set(table.enabled, enabled)
                    .where(condition)
                    .update();
            if (!update) return R.fail("修改状态信息失败");
        }
        return R.ok();
    }

    @Override
    public R<Object> dropData(String headStaffUid, String headStaffName, String uid) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工参数缺少");
        if (StringUtils.isBlank(uid))
            return R.fail("分类参数缺少");

        CourseTrainTypes courseTypes = getMapper().selectOneByCondition(table.uid.eq(uid));
        if (courseTypes == null) return R.fail("分类获取失败");
        Long id = courseTypes.getId();

        QueryCondition condition = QueryCondition.createEmpty()
                .and(table.nodes.likeLeft(courseTypes.getNodes()))
                .and(table.id.ne(id));
        List<CourseTrainTypes> list = getMapper().selectListByCondition(condition);
        if (CollectionUtils.isNotEmpty(list)) return R.fail("有子菜单不能删除");

        // 是最后一层
        long courseCnt = courseTrainService.getByTypeIdCnt(uid);
        if (courseCnt > 0) return R.fail("分类下有资料不能删除");

        QueryCondition dorpCondition = QueryCondition.createEmpty()
                .and(table.id.eq(id).or(table.parentId.eq(id)));
        long l = getMapper().deleteByCondition(dorpCondition);
        if (l <= 0) return R.fail("删除失败");

        return R.ok();
    }

    @Override
    public R<Object> upOrDown(String headStaffUid, String headStaffName, String uid, Integer type) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工参数缺少");
        if (StringUtils.isBlank(uid))
            return R.fail("分类参数缺少");
        if (type == null)
            return R.fail("操作类型参数缺少");

        CourseTrainTypes data = getMapper().selectOneByCondition(table.uid.eq(uid));
        if (data == null) return R.fail("分类获取失败");
        Long parentId = data.getParentId();
        Integer showOrder = data.getShowOrder();
        if (type.equals(1)) {
            // 上移
            QueryCondition condition = QueryCondition.createEmpty()
                    .and(table.parentId.eq(parentId))
                    .and(table.showOrder.lt(showOrder));

            QueryWrapper wrapper = QueryWrapper.create()
                    .where(condition)
                    .orderBy(table.showOrder.desc());

            CourseTrainTypes preData = getMapper().selectOneByQuery(wrapper);
            if (preData == null) return R.fail("已在最前");
            // 和前一条记录的序号互换
            Integer prevOrderNum = preData.getShowOrder();
            Integer curOrderNum = data.getShowOrder();
            // 序号互换
            boolean updatePre = updateShowOrder(preData.getId(), curOrderNum);
            boolean updated = updateShowOrder(data.getId(), prevOrderNum);
            if (!updatePre || !updated) return R.fail("修改序号失败");
        } else if (type.equals(2)) {
            // 下移
            QueryCondition condition = QueryCondition.createEmpty()
                    .and(table.parentId.eq(parentId))
                    .and(table.showOrder.gt(showOrder));

            QueryWrapper wrapper = QueryWrapper.create()
                    .where(condition)
                    .orderBy(table.showOrder.desc());
            CourseTrainTypes backData = getMapper().selectOneByQuery(wrapper);
            if (backData == null) return R.fail("已在最后");
            // 和后一条记录的序号互换
            Integer backOrderNum = backData.getShowOrder();
            Integer curOrderNum = data.getShowOrder();
            // 序号互换
            boolean updateBack = updateShowOrder(backData.getId(), curOrderNum);
            boolean updated = updateShowOrder(data.getId(), backOrderNum);
            if (!updateBack || !updated) return R.fail("修改序号失败");
        } else {
            return R.fail("类型错误");
        }
        return R.ok();
    }

    @Override
    public CourseTrainTypes getInfoByUid(String mainTypeUid) {
        return getMapper().selectOneByCondition(table.uid.eq(mainTypeUid));
    }

    @Override
    public R<Object> uploadExam(String headStaffUid, String headStaffName, String uid, String examRequire, String examUrl) {
        if (StringUtils.isBlank(headStaffUid))
            return R.fail("总部员工参数缺少");
        if (StringUtils.isBlank(uid))
            return R.fail("分类参数缺少");
        if (StringUtils.isBlank(examRequire))
            return R.fail("考试要求参数缺少");

        CourseTrainTypes data = getMapper().selectOneByCondition(table.uid.eq(uid));
        if (data == null)
            return R.fail("分类获取失败");
        if (data.getLevelEnd() != 1)
            return R.fail("非最后一层不能上传考试");

        if (StringUtils.isNotBlank(examRequire))
            data.setExamRequire(examRequire);

        if (StringUtils.isNotBlank(examUrl))
            data.setExamUrl(examUrl);

        boolean updated = saveOrUpdate(data);
        return updated ? R.ok() : R.fail("修改失败");
    }

    public boolean updateShowOrder(Long id, Integer orderNum) {
        return UpdateChain.of(CourseTrainTypes.class)
                .set(table.showOrder, orderNum)
                .where(table.id.eq(id))
                .update();
    }
}
